<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Document</title>
</head>

<body></body>
<script>
    function Book(title, pages, isbn) {
        // 创建了一个 Book 类
        this.title = title;
        this.pages = pages;
        this.isbn = isbn;
    }
    Book.prototype.author = function () {
        console.log(111);
    };
    // 创建一个 book 对象
    let book = new Book("title", "pages", "isbn");
    // console.log(book);
    book.title = "母猪的产后护理";
    console.log(book);
    /* 以上是 es5 的写法 */
    /* 以下是 es6 的写法 */
    // 注意：函数声明和类声明之间的一个重要区别在于，函数声明会提升，类声明不会。
    // 在 class 内部可以使用 get 与 set 关键字，对某个属性设置存值函数和取值函数，拦截该属性的读取行为。
    // 定义类也有两种主要方式：类声明和类表达式。这两种方式都使用class关键字加大括号：
    /* 
        // 类声明
        class Person {}
        // 类表达式
        const TestPerson = class {}
    */
    // 定义 NewBook 类
    class NewBook {
        constructor(title, pages, isbn) {
            // 创建了一个 Book 类
            this.title = title; // 类的方法内部如果含有this，它默认指向类的实例。
            this.pages = pages;
            this.isbn = isbn;
        }
        // 不推荐原型绑定函数如下这么用，因为类的方法内部如果含有 this，它默认指向类的实例。但是某些情况是指向当前执行环境
        /* 
            const { author } = a
            console.log(author());
         */
        // author() {
        //     console.log(this);
        //     return 1
        // }
        // 推荐使用箭头函数，这样 this 始终都指向对象
        author = () => {
            console.log("NewBook", this);
        }
    }
    const newBook = new NewBook("新书", "100", "0");    // 使用的时候，必须用 new 来调用类
    newBook.title = "母猪的产后护理";
    console.log(newBook);

    // 类的继承
    class ITBook extends NewBook {  // 扩展原来父类并继承其行为
        constructor(sort, title, pages, isbn) {
            super(title, pages, isbn);  // 引用父类的构造函数，相当于指向父类的 this
            this.sort = sort;
            this._title = title;
        }
        technology = () => {
            console.log("ITBook", this);
        }
        get title() {
            console.log("get");
            // 注意 get 函数没有任何参数
            return this._title
        }
        set title(val) {
            console.log('set :>> ', val);
            this._title = val
        }
    }
    const itbook = new ITBook("IT", "JS书籍", "100", "1")
    console.log(itbook);
    // itbook.sort = "history"
</script>

</html>